<template>
  <tm-app class="app-container">
    <tm-navbar :title="workTitle" v-if="showPrimaryOrDetail === 'Primary'"></tm-navbar>
    <tm-navbar :title="formTitle" v-if="showPrimaryOrDetail === 'Detail'" :hideBack="true">
      <template v-slot:left>
        <tm-icon _class="pointer pb-12 pt-12 px-24" name="tmicon-angle-left" @click="switchToForm('Primary')"></tm-icon>
      </template>
    </tm-navbar>
    <view class="content-container">
      <view v-if="!hasConfig" class="full-height">
        <workState style="height: 100%" :type="workSubType" />
      </view>
      <view v-else>
        <workMain
          v-if="showPrimaryOrDetail === 'Primary'"
          :service="service"
          :node="node"
          :fields="fields"
          :type="showPrimaryOrDetail"
          :rules="rules"
          :workFormData="workPrimaryFormData"
          :workDetailData="workDetailFormData"
          :detailFormData="detailForm"
          :content="content"
          :btnRules="btnRules"
          @ValuesChange="workValuesChange"
          @changeType="switchToForm"
          @validationChange="handleValidationChange"
          @deleteDetailData="deleteDetailData"
        />
        <workMain
          v-if="showPrimaryOrDetail === 'Detail'"
          :fields="detailFields"
          :workFormData="workDetailFormData![detailFormId].find((item:any) => item.nodeId === detailNodeId)!.after.find((item:any) => item.id === detailId)"
          @ValuesChange="workValuesChangeDetail"
          @validationChange="handleValidationChange"
        />
        <workBtn :type="showPrimaryOrDetail" :canSubmit="canSubmit" @save="save" @delete="deleteChange" :isdraft="isdraft" />
      </view>
    </view>
  </tm-app>
</template>

<script lang="ts" setup>
import { ref, shallowRef, onMounted, getCurrentInstance } from 'vue'
import workState from '@/components/work/workState.vue'
import workMain from '@/components/work/workMain.vue'
import workBtn from '@/components/work/workBtn.vue'
import { onLoad } from '@dcloudio/uni-app'
import orgCtrl from '@/ts/controller'
import { AddNodeType } from '@/utils/work'
import WorkFormService from '@/ts/core/work/scripting/WorkFormService'
import { setDefaultField } from '@/ts/core/work/scripting/FormService'
import FormService from '@/ts/core/work/scripting/FormService'
import { getNodeByNodeId } from '@/utils/work'
import { mapErrorToValidateInfo } from '@/ts/core/work/scripting/js/util'
import { kernel, schema, model } from '@/ts/base'
import { cloneDeep } from 'lodash'
// 是否有配置项的标志，后续会根据实际业务逻辑来设置
const hasConfig = ref(false)
const canSubmit = ref(false)
const params = ref()
const node = ref<model.WorkNodeModel | undefined>(undefined)
const workTitle = ref('办事名称')
const formTitle = ref('表单名称')
const service = shallowRef<WorkFormService>()
const service_current = ref<any>(null)
const fields = ref<(schema.XGroups | model.FieldModel)[]>()
const detailFields = ref<(schema.XGroups | model.FieldModel)[]>()
const workPrimaryFormData = ref<schema.XThing | undefined>()
const rules = ref()
const btnRules = ref()
const detailForm = ref()
const workDetailFormData = ref({})
const showPrimaryOrDetail = ref('Primary')
const detailId = ref()
const detailNodeId = ref()
const detailFormId = ref()
const applyCurrent = ref()
const loading = ref(false)
const staggingId = ref<string | undefined>(undefined)
const staggingType = ref<string | undefined>(undefined)
const staggingContent = ref<string>('')
const content = ref('')
const staggingInstance = ref()
const isdraft = ref(false)
const workSubType = ref('unconfigured')
const gatewayData = ref(new Map<string, string[]>())
onLoad(async options => {
  if (!options) return
  if (!options.id) return
  if (options) {
    try {
      // 解码并解析参数
      const parsedData = options
      params.value = parsedData // 存储参数
      uni.showLoading({ title: '加载中...' })
    } catch (error) {
      console.error('解析参数错误:', error)
    }
  }
})
onMounted(() => {
  const instance = getCurrentInstance()!.proxy
  const eventChannel = instance!.getOpenerEventChannel()
  if (params.value) {
    searchWork()
  }
  eventChannel.on('workData', async function (data) {
    staggingType.value = data.type
    if (staggingType.value) {
      isdraft.value = true
    }
    staggingId.value = data.data
    staggingContent.value = data.content
    if (staggingType.value === 'draft') {
      staggingInstance.value = data.instance
    }
    await searchWork()
  })
})
const handleValidationChange = (isValid: boolean) => {
  canSubmit.value = isValid
}
const searchWork = async () => {
  try {
    if (!params.value) {
      uni.hideLoading()
      return
    }
    const fileData = await orgCtrl.searchWork(params.value.belongId, params.value.id)
    if (!fileData) {
      hasConfig.value = false
      uni.hideLoading()
      return
    }
    const apply = await fileData.createApply(undefined, undefined)
    if (!apply) {
      hasConfig.value = false
    } else {
      workTitle.value = apply.metadata.title
      applyCurrent.value = apply
      if (['财务', '总账'].includes(apply.applyType) || apply.instanceData.node.children?.type !== AddNodeType.END) {
        init()
      }
    }
    uni.hideLoading()
  } catch (error) {
    uni.hideLoading()
    uni.showToast({
      title: '加载失败',
      icon: 'error'
    })
  }
}
const init = () => {
  if (staggingInstance.value) {
    const parsedData = JSON.parse(staggingInstance.value.data)
    Object.assign(applyCurrent.value.instanceData, parsedData, {
      node: applyCurrent.value.instanceData.node
    })
  }
  service.value = new WorkFormService(applyCurrent.value.target, applyCurrent.value.instanceData, true, applyCurrent.value.reception)
  hasConfig.value = true
  const ret = service.value.init()
  if (ret instanceof Error) {
    if (Array.isArray(ret.cause)) {
      service.value.handlingResult(ret.cause.map(e => mapErrorToValidateInfo(e, '初始化')))
    } else {
      service.value.handlingResult([mapErrorToValidateInfo(ret, '初始化')])
    }
  }
  node.value = getNodeByNodeId(applyCurrent.value.instanceData.node.id, applyCurrent.value.instanceData.node)
  btnRules.value = applyCurrent.value.instanceData.node.forms
  initForm()
}
const getData = () => {
  let d: schema.XThing | undefined
  d = service_current.value!.formData.after.at(-1)
  if (d && node.value?.primaryForms[0].id) {
    service.value!.updatePrimaryData(node.value?.primaryForms[0].id, d)
    service_current.value!.initRules(d)
  }
  return d
}
const initForm = () => {
  if (service.value && node.value && node.value.primaryForms.length > 0) {
    service_current.value = new FormService(node.value.primaryForms[0] as schema.XForm, service.value)
    if (node.value.primaryForms[0].typeName === '主表' || node.value.primaryForms[0].typeName === '表单') {
      const data = getData()
      workPrimaryFormData.value = data
      if (service_current.value.fields) {
        const attributes: (schema.XGroups | model.FieldModel)[] = cloneDeep(service_current.value.fields)
        if (service_current.value.form.groups?.length) {
          service_current.value.form.groups.forEach((group: any) => {
            attributes.splice(group.index, 0, group)
          })
        }
        fields.value = attributes
        rules.value = [...(service_current.value.formData?.rules ?? []), ...(service_current.value.work?.model.rules ?? [])]
        // const rules = [...(service_current.value.formData?.rules ?? []),...(service_current.value.work?.model.rules ?? [])].filter((a) => a.destId == field.id)
      }
    }
  }
  if (node.value && service.value) {
    detailForm.value = [...node.value.detailForms]
    node.value.detailForms.forEach((item: any) => {
      const formData = service.value!.getFormData(item, node.value!.id, '子表')
      if (formData) {
        if (!workDetailFormData.value[item.id]) {
          workDetailFormData.value[item.id] = []
        }
        if (staggingInstance.value && workDetailFormData.value[item.id][0].after.length === 0) {
          //草稿箱进的数据
          workDetailFormData.value[item.id] = []
        }
        if (staggingType.value !== 'create') {
          workDetailFormData.value[item.id].push(formData)
        }
      }
    })
  }
}
const workValuesChange = (field: string, value: any) => {
  if (field === 'content') {
    content.value = value
  } else {
    if (!service_current.value) return
    service_current.value.onValueChange(field, value, workPrimaryFormData.value)
  }
}
const workValuesChangeDetail = (field: string, currentvalue: any) => {
  if (workDetailFormData.value) {
    workDetailFormData.value[detailFormId.value]
      .find((item: any) => item.nodeId === detailNodeId.value)!
      .after.find((item: any) => item.id === detailId.value)![field] = currentvalue
  }
}

const switchToForm = async (type: string, formType?: string, nodeId?: string, id?: string, formId?: string) => {
  showPrimaryOrDetail.value = type
  if (formType === 'edit' && workDetailFormData.value && service.value && id && nodeId && formId) {
    detailFields.value = service.value.model.fields[formId]
    formTitle.value = workDetailFormData.value![formId].find((item: any) => item.nodeId === nodeId)!.after.find((item: any) => item.id === id)!.name
    detailId.value = id
    detailNodeId.value = nodeId
    detailFormId.value = formId
  }
  if (formType === 'add' && service.value && nodeId && formId) {
    const res = await kernel.createThing(service.value.belong.id, [], '')
    if (res.success && Array.isArray(res.data) && res.data.length > 0) {
      await setDefaultField(res.data[0], service.value.model.fields[formId], service.value.belong)
      const initialValues = res.data[0]
      initialValues.name = workDetailFormData.value[formId].find((item: any) => item.nodeId === nodeId)?.formName as string
      workDetailFormData.value[formId].find((item: any) => item.nodeId === nodeId)!.after.push(initialValues)
      detailFields.value = service.value.model.fields[formId]
      formTitle.value = initialValues.name
      detailId.value = initialValues.id
      detailNodeId.value = nodeId
      detailFormId.value = formId
    }
  }
}
const save = async () => {
  //保存和提交
  if (showPrimaryOrDetail.value === 'Primary') {
    if (loading.value) return
    loading.value = true
    try {
      applyCurrent.value.instanceData.data = {
        ...applyCurrent.value.instanceData.data,
        ...workDetailFormData.value
      }
      // 创建办事实例
      const instance = await applyCurrent.value.createApply(
        applyCurrent.value.target.spaceId,
        content.value,
        new Map() // 自由节点之类的再配置
      )

      if (instance) {
        // 提交成功
        uni.showToast({
          title: '提交成功',
          icon: 'success'
        })
        hasConfig.value = false
        workSubType.value = 'success'
      } else {
        uni.showToast({
          title: '提交失败',
          icon: 'error'
        })
      }
    } catch (error) {
      uni.showToast({
        title: '提交失败：' + error,
        icon: 'error'
      })
    } finally {
      loading.value = false
    }
  } else {
    await switchToForm('Primary')
  }
}
const deleteChange = async () => {
  //存草稿和删除
  if (showPrimaryOrDetail.value === 'Primary' && staggingType.value !== undefined) {
    applyCurrent.value.instanceData.data = {
      ...applyCurrent.value.instanceData.data,
      ...workDetailFormData.value
    }
    //存草稿只有列表办事才行
    const info: { content: string } = { content: staggingContent.value }
    const instance = await applyCurrent.value.staggingApply(info.content, gatewayData.value, orgCtrl.user.workStagging, staggingId.value)
    if (instance) {
      orgCtrl.user.workStagging.cache.push(instance)
      uni.showToast({
        title: '暂存成功',
        icon: 'success'
      })
      hasConfig.value = false
      workSubType.value = 'draft'
    } else {
      uni.showToast({
        title: '暂存失败',
        icon: 'error'
      })
    }
  } else {
    //删除
    deleteDetailData(detailNodeId.value, detailId.value)
  }
}
const deleteDetailData = async (nodeId?: string, id?: string) => {
  if (!nodeId || !id || !workDetailFormData.value) return
  const detailForm = workDetailFormData.value[detailFormId.value].find(item => item.nodeId === nodeId)
  if (detailForm && detailForm.after) {
    const index = detailForm.after.findIndex(item => item.id === id)
    if (index !== -1) {
      detailForm.after.splice(index, 1)
      await switchToForm('Primary')
    }
  }
}
</script>

<style scoped>
.app-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.content-container {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.full-height {
  height: 100%;
  display: flex;
  flex-direction: column;
}
</style>
